/**
 * Copyright (c) 2010-2011 julewa.com.  
 * All rights reserved. 
 * 
 * @author Huang Benhua
 * @date 2011-2-20
 * 
**/
package com.julewa;

import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

import org.springframework.context.ApplicationContext;

import com.julewa.db.Entity;
import com.julewa.db.ibatis.IbatisDB;
import com.julewa.db.ibatis.IbatisTestLoader;
import com.julewa.db.ibatis.IbatisTransaction;
import com.julewa.loading.SpringLoader;
import com.julewa.loading.SystemUtils;
import com.julewa.utils.ClassUtils;

/*
 * 用于独立启动应用环境
 */
@SuppressWarnings("unchecked")
public final class SystemContext {
	
	private ApplicationContext context = null;
	public SystemContext(Class<?> ... classes){
		//ready
		System.out.println("[SYSTEM]Loading application context ...");
		SystemUtils.initialize();
		//
		Map<String, String> beans = new HashMap<String, String>();
		for(Class<?> c:classes){
			System.out.println("[SYSTEM]Loading " + c.getCanonicalName());
			SpringLoader.push_class(beans, c);
		}
		SpringLoader.push_class(beans, IbatisDB.class);
		SpringLoader.push_class(beans, IbatisTransaction.class);
		SpringLoader.push_class(beans, IbatisTestLoader.class);
		//load
		IbatisTestLoader.load();
		context = SpringLoader.load_test_context(beans);
		System.out.println("[SYSTEM]Application context loaded.");
	}
	
	public boolean isValid(){
		return context != null;
	}
	
	public <T> T getInstanceOf(Class<T> type){
		Map<String, T> map = getInstancesOf(type);
		if(map == null)return null;
		return map.values().iterator().next();
	}
	
	public <T> Map<String, T> getInstancesOf(Class<T> type){
		if(context == null)return null;
		Map<String, T> map = context.getBeansOfType(type);
		if(map == null || map.isEmpty())return null;
		return map;
	}
	
	public Object getInstanceOf(String id){
		if(context == null)return null;
		return context.getBean(id);
	}
	
	public <T> T getInstanceOf(Class<T> type, String id){
		if(context == null)return null;
		return (T)context.getBean(id, type);
	}
	

	private static final Map<Class<?>, Class<?>> _KEY_TYPES_ 
		= new HashMap<Class<?>, Class<?>>(); 
	public static Class<?> getEntityKeyType(Class<?> entc){
		Class<?> c = _KEY_TYPES_.get(entc);
		if(c != null)return c;
		Type[] t = ClassUtils.getActualArgumentTypes(entc, Entity.class);
		if(t != null && t.length > 0){
			c = (Class<?>)t[0];
		}
		_KEY_TYPES_.put(entc, c);
		return c;
	}
}
